#include "Graph3D.h"

#include <QList>
#include <QGuiApplication>

#include <algorithm>
#include <vector>

namespace dv = QtDataVisualization;

Graph3D::Graph3D()
{
    axisZ()->setReversed(true);

    _theme_light = new dv::Q3DTheme(dv::Q3DTheme::ThemePrimaryColors);
    addTheme(_theme_light);
    _theme_dark = new dv::Q3DTheme(dv::Q3DTheme::ThemeIsabelle);
    addTheme(_theme_dark);

    resetTheme();

    setReflection(false);
    setShadowQuality(QAbstract3DGraph::ShadowQualityMedium);
}

void Graph3D::handleInitialization(const QString & )
{
    for(auto s : seriesList()) {
        removeSeries(s);
        delete s;
    }
}

QtDataVisualization::QScatter3DSeries * Graph3D::handleAddSeries(const QString & series_name, int mesh)
{
    dv::QScatter3DSeries * series = new dv::QScatter3DSeries();

    series->setName(series_name);
    series->setMesh(static_cast<dv::QAbstract3DSeries::Mesh>(mesh));

    addSeries(series);

    // if (auto it=_series_point_counts.find(series_name); it == _series_point_counts.end())
    //     _series_point_counts[series_name] = 1000;

    return series;
}

void Graph3D::handleAddPoint(const QString & series_name, float x, float y, float z)
{
    QList<dv::QScatter3DSeries *> series_list = seriesList();
    auto s_it = std::find_if(series_list.begin(), series_list.end(), 
                            [&series_name](const dv::QScatter3DSeries * s) { 
                                return series_name == s->name(); 
                            });

    dv::QScatter3DSeries * series;
    if (s_it == series_list.end())
        series = handleAddSeries(series_name, dv::QAbstract3DSeries::Mesh::MeshMinimal);
    else
        series = *s_it;

    if (!series)
        return;

    series->dataProxy()->addItem(QVector3D{x,y,z});

    int size = series->dataProxy()->array()->size();
    series->setSelectedItem(size - 1);

    if (auto it = _series_point_counts.find(series_name); it != _series_point_counts.end())
        if (it->second != 0 && size > it->second)
            series->dataProxy()->removeItems(0, size - it->second);
}

void Graph3D::handleSetPointsCount(const QString & series_name, int count)
{
    _series_point_counts[series_name] = count;
}

void Graph3D::resetTheme()
{
    QPalette palette = QGuiApplication::palette();
    if (palette.window().color().toCmyk().black() > 128)
        setActiveTheme(_theme_dark);
    else
        setActiveTheme(_theme_light);
}

